import { Injectable } from '@angular/core'
import { TreeModel } from 'ng2-tree';
import { Http, RequestOptionsArgs, Headers } from '@angular/http';
import { GeoData, ToolIOData, postData, uploadResponseData, DataForRunModel } from '../data_model/data-model'

import { DataTransmissionService } from './data-transmission.service';
@Injectable()
export class ModelContainerService {

    Rslt: any;
    requestOptionsArgs: RequestOptionsArgs;
    Ip: String;
    constructor(private http: Http,
        private dataTransmissionService: DataTransmissionService) {
        //http://172.21.212.119:8060/modelser/inputdata/json/59b61e04c0d867130c822f66
        let headers = new Headers();
        headers.set('enctype', 'multipart/form-data');
        this.requestOptionsArgs = {
            headers: headers
        };
        this.Ip = '127.0.0.1';
    }

    getModelInfo(ToolId: string): Promise<ToolIOData> {
        return new Promise((resolve, reject) => {

            this.http.get('/api/info',
                {
                    search: {
                        'ip': this.Ip,
                        'id': ToolId
                    }
                }).toPromise().then(data => {
                    let RsltJson = JSON.parse(data.json().data);
                    if (!RsltJson) {
                        console.log("Result format is not correct.");
                        reject(RsltJson);
                    } else {
                        if (RsltJson && RsltJson.result === 'err') {
                            console.log(RsltJson);
                            reject(RsltJson);
                        } else if (RsltJson && RsltJson.result === 'suc') {
                            return RsltJson.data;
                        }
                    }
                }, error => {
                    console.log(error);
                    reject(error);
                }).then(data => {
                    let inputDataArray = new Array<GeoData>();
                    let outputDataArray = new Array<GeoData>();
                    let StateId = '';
                    let StateName = '';
                    let StateDesc = '';
                    if (data && data.States && data.States[0] && data.States[0].$ && data.States[0].Event) {
                        StateId = data.States[0].$.id;
                        StateName = data.States[0].$.name;
                        StateDesc = data.States[0].$.description;
                        let EventCount = data.States[0].Event.length;
                        for (let i = 0; i < EventCount; i++) {

                            let CurrentEvent = data.States[0].Event[i].$;

                            let CurrentGeoData = new GeoData(CurrentEvent.name,
                                CurrentEvent.description,
                                CurrentEvent.optional);

                            if (CurrentEvent.type === 'response') {
                                inputDataArray.push(CurrentGeoData);
                            } else {
                                outputDataArray.push(CurrentGeoData)
                            }
                        }
                        resolve(new ToolIOData(StateId, StateName, StateDesc, inputDataArray, outputDataArray));
                    } else {
                        reject("Unresolved data");
                    }
                })
        })
    }

    runModel(modelId: string,
        URData: Array<uploadResponseData>): Promise<any> {
        //预处理数据
        let inputData = [];

        URData.forEach((value, index) => {

            let tempStr = value.ResponseData._body;
            let gd_id = JSON.parse(JSON.parse(tempStr).data).gd_id;
            if (gd_id) {
                inputData.push(new DataForRunModel(value.StateId,
                    value.StateName,
                    value.StateDesc,
                    value.Event,
                    gd_id));
            }
        })
        return new Promise((resolve, reject) => {
            let inputDataParameter = JSON.stringify(inputData);

            this.http.get("/api/run", {
                search: {
                    'id': modelId,
                    'ip': this.Ip,
                    'ac': 'run',
                    'inputdata': inputDataParameter
                }
            }).toPromise().then(responseData => {
                let RsltJson = JSON.parse(responseData.json().data);
                if (!RsltJson) {
                    console.log("Result format is not correct.");
                    reject(RsltJson);
                } else {
                    if (RsltJson.res === 'err') {
                        console.log(RsltJson);
                        reject(RsltJson);
                    } else if (RsltJson.res === 'suc') {
                        resolve(RsltJson.msr_id);
                    }
                }
            }, error => {
                reject("error to run model");
            })
        })
    }

    uploadInputData(uploadData: Array<postData>): Promise<any> {
        return new Promise((resolve, reject) => {

            this.PromiseForEach(uploadData, (value) => {

                let fd = new FormData();
                fd.append("stateid", value.stateid);
                fd.append("eventname", value.eventname)
                fd.append('myfile', value.myfile);

                return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        this.http.post("/api/upload", fd, {
                            search: {
                                'ip': this.Ip,
                            }
                        }).toPromise().then(data => {
                            resolve(data);
                        }, error => {
                            reject(error);
                        })
                    }, 100);
                })
                // return 
            }).then((data) => {
                resolve(data);
            }).catch((err) => {
                console.log(err);
                reject(err);

            });
        })

    }

    getGeoJson(dataId: string): Promise<any> {

        return new Promise((resolve, reject) => {

            this.http.get("/api/geojson", {
                search: {
                    'id': dataId,
                    'ip': this.Ip,
                }
            }).toPromise().then(data => {

                resolve(data);

            })
        })
    }

    waitForResult(msr_id: string): Promise<any> {
        return new Promise((resolve, reject) => {
            let timer = setInterval(() => {
                this.getModelRunRecord(msr_id).then(res => {
                    let JsonObject = JSON.parse(JSON.parse(res._body).data);
                    if (JsonObject.data && JsonObject.data.msr_time) {
                        if (JsonObject.data.msr_time !== 0) {
                            this.dataTransmissionService.sendModelRunRecord(res);
                            clearInterval(timer);
                        }
                    }
                }, error => {
                    console.log(error);
                    clearInterval(timer);
                })

            }, 1000);
            resolve('waiting for result...');

        })

    }

    getModelRunRecord(msr_id: string): Promise<any> {
        return new Promise((resolve, reject) => {
            this.http.get('/api/instance', {
                search: {
                    'ip': this.Ip,
                    'id': msr_id
                }
            }).toPromise().then(res => {

                resolve(res);
            }, error => {
                reject(error);
            })
        })
    }

    //////////////////////////////////////private method/////////////////////////////////////////////////////
    private PromiseForEach(dataArray: Array<postData>, callback: Function): Promise<any> {
        let realResult = [];
        let TempResult = Promise.resolve();
        dataArray.forEach((value, index) => {
            //将连接了新的.then的result替换掉原来的，最后所得到一长串的result.then().then().then()...达到串行的效果
            //callback为异步操作，希望返回的是一个Promise<any>对象
            TempResult = TempResult.then(() => {
                return callback(value).then((callbackRes) => {
                    realResult.push(new uploadResponseData(
                        value.stateid,
                        value.statename,
                        value.statedesc,
                        value.eventname,
                        callbackRes));
                })
            })
        })
        return TempResult.then(() => {
            return realResult;
        })
    }

}